/*
 * CcLink.c
 *
 *  Created on: 2012-5-14
 *      Author: guanxiaoying
 */

#include "../coredef.h"
#include "cc.h"
static AST ccNewLinkage( astSym, usDeclKind, usLinkKind ){
	AST astCcLinkage;
	AST astpreOne;
	AST astNewChain;
	AST astOldChain;
	BOOL bExist = FALSE;

	astCcLinkage = stCCLinkageAccess.findLinkage( astSym );
	if(astCcLinkage == 0 ){
		astCcLinkage = stCCLinkageAccess.addLinkage( astSym );
	}else{
		bExist = TRUE;
	}
	if( astCcLinkage == 0 ){
		return 0;
	}
	if( bExist ){
		if (stCCLinkageAccess.bExternal.get( astCcLinkage )){
			if( usLinkKind == LINK_INTERN ){
				if( ( stCCLinkageAccess.definitionChain.get( astCcLinkage ) != 0
								 || stCCLinkageAccess.tenDeclChain.get( astCcLinkage ) != 0 )){
					CcThrowWarning( CC_DECL_DOUBLE_LINKAGE,
							stSymbolInfoAccess.codeScp.get( astSym ), NULL, NULL );
					astpreOne = stUniteChainAccess.parameter_sym.get(
							stCCLinkageAccess.allChain.get( astCcLinkage ) );
					CcThrowWarning( CC_DECL_DOUBLE_LINKAGE1ST,
							stSymbolInfoAccess.codeScp.get( astpreOne ), NULL, NULL );
					stCCLinkageAccess.definitionChain.set( astCcLinkage, 0 );
					stCCLinkageAccess.tenDeclChain.set( astCcLinkage, 0 );
				}
			}
		}else{
			if( usLinkKind == LINK_EXTERN ){
				CcThrowWarning( CC_DECL_DOUBLE_LINKAGE,
						stSymbolInfoAccess.codeScp.get( astSym ), NULL, NULL );
				astpreOne = stUniteChainAccess.parameter_sym.get(
						stCCLinkageAccess.allChain.get( astCcLinkage ) );
				CcThrowWarning( CC_DECL_DOUBLE_LINKAGE1ST,
						stSymbolInfoAccess.codeScp.get( astpreOne ), NULL, NULL );
				return 0;
			}else{
				usLinkKind = LINK_INTERN;
			}
		}
	}
	if( usLinkKind == LINK_INTERN ){
		stCCLinkageAccess.bExternal.set( astCcLinkage, FALSE );
	}else{
		stCCLinkageAccess.bExternal.set( astCcLinkage, TRUE );
	}
	if( usDeclKind == xDECKIND_DEFINITION ){
		stUniteChainAccess.alloc(1);
		astNewChain = stUniteChainAccess.getMax();
		stUniteChainAccess.parameter_sym.set( astNewChain, astSym );
		astOldChain = stCCLinkageAccess.definitionChain.get( astCcLinkage );
		stUniteChainAccess.before.set( astOldChain, astNewChain );
		stUniteChainAccess.next.set( astNewChain, astOldChain );
		stCCLinkageAccess.definitionChain.set( astCcLinkage, astNewChain );
		if( astOldChain != 0 ){
			astpreOne = stUniteChainAccess.parameter_sym.get( astOldChain );
			CcThrowWarning( CC_SYMBOL_REDEFINITION,
					stSymbolInfoAccess.codeScp.get( astSym ), NULL, NULL );
			CcThrowWarning( CC_SYMBOL_REDEFINITION1ST,
					stSymbolInfoAccess.codeScp.get( astpreOne ), NULL, NULL );

		}
	}else if( usDeclKind == xDECKIND_TENDEFINITION ){
		stUniteChainAccess.alloc(1);
		astNewChain = stUniteChainAccess.getMax();
		stUniteChainAccess.parameter_sym.set( astNewChain, astSym );
		astOldChain = stCCLinkageAccess.tenDeclChain.get( astCcLinkage );
		stUniteChainAccess.before.set( astOldChain, astNewChain );
		stUniteChainAccess.next.set( astNewChain, astOldChain );
		stCCLinkageAccess.tenDeclChain.set( astCcLinkage, astNewChain );
	}
	stUniteChainAccess.alloc(1);
	astNewChain = stUniteChainAccess.getMax();
	stUniteChainAccess.parameter_sym.set( astNewChain, astSym );
	astOldChain = stCCLinkageAccess.allChain.get( astCcLinkage );
	stUniteChainAccess.before.set( astOldChain, astNewChain );
	stUniteChainAccess.next.set( astNewChain, astOldChain );
	stCCLinkageAccess.allChain.set( astCcLinkage, astNewChain );
	return astCcLinkage;
}


VOID CcLinkageSet(AST astSym, AST astDeclarator){
	AST     astValPosInfo ;
	AST   astTypeDeclInfo ;
	U2  usMemClassInfo ;		/* 記憶クラス指定子			*/
	U2  usDeclKind = 0;			/* 宣言種類				*/
	U2  usTypeDeclKind ;
	U2  usLinkKind=LINK_UNSURE;
	AST     astLink ;

	if( astSym == 0 ){
		return ;
	}
	astValPosInfo = stBlockNestAccess.getMax() ;

	astTypeDeclInfo =  stSymbolInfoAccess.type.get( astSym );
	usMemClassInfo = stSymbolInfoAccess.symClass.get( astSym );
	usTypeDeclKind = stDeclaratorAccess.declaratorKind.get( astDeclarator ) ;

	if( astValPosInfo == MIN_ARRAY ){
		/* global */
	    if( CcTypeIsFunction( astTypeDeclInfo )
	    	&& stSymbolInfoAccess.functionBody.get( astSym ) != 0 ){
	    	if( usMemClassInfo == CLASS_STATIC ){
	    		usLinkKind = LINK_INTERN;
	    	}else{
	    		usLinkKind = LINK_EXTERN;
	    	}
	    	usDeclKind = xDECKIND_DEFINITION ;
	    }else if( CcTypeIsFunction( astTypeDeclInfo )){
	    	usLinkKind = LINK_UNSURE;
	    	usDeclKind = xDECKIND_DECLARATION ;
	    }else if( usTypeDeclKind == xDECLARATOR_INIT ){
	    	/* initialized. definition */
	    	if( usMemClassInfo == CLASS_STATIC ){
	    		usLinkKind = LINK_INTERN;
	    	}else{
	    		usLinkKind = LINK_EXTERN;
	    	}
	    	usDeclKind = xDECKIND_DEFINITION ;
	    }else if( usMemClassInfo == 0 ){
	    	usLinkKind = LINK_EXTERN;
	    	usDeclKind = xDECKIND_TENDEFINITION ;
	    }else if( usMemClassInfo == CLASS_STATIC ){
	    	usLinkKind = LINK_INTERN;
	    	usDeclKind = xDECKIND_TENDEFINITION ;
	    }else{
	    	usLinkKind = LINK_UNSURE;
	    	usDeclKind = xDECKIND_DECLARATION ;
	    }
	}else{
		if( usMemClassInfo == CLASS_EXTERN  ){
			usLinkKind = LINK_UNSURE;
			usDeclKind = xDECKIND_DECLARATION ;
			if( CcTypeIsFunction( astTypeDeclInfo )
				&& stSymbolInfoAccess.functionBody.get( astSym ) != 0 ){
				usDeclKind = 0;
				CcThrowWarning( CC_DECL_EXTERN_FUNC_IN_FUNC,
						stSymbolInfoAccess.codeScp.get( astSym ),
						stSymbolInfoAccess.name.get( astSym ), NULL );
			}else if( usTypeDeclKind == xDECLARATOR_INIT ){
				CcThrowWarning( CC_DECL_VARI_INBLOCK_EXTERN_INITIALLED,
						stSymbolInfoAccess.codeScp.get( astSym ),
						stSymbolInfoAccess.name.get( astSym ), NULL );
				usDeclKind = 0;
			}
		}else{
			usDeclKind = 0;
			if( CcTypeIsFunction( astTypeDeclInfo )
				&& stSymbolInfoAccess.functionBody.get( astSym ) != 0 ){
				usDeclKind = 0;
				CcThrowWarning( CC_DECL_FUNC_IN_FUNC,
						stSymbolInfoAccess.codeScp.get( astSym ),
						stSymbolInfoAccess.name.get( astSym ), NULL );
			}
		}
	}
	if( usDeclKind == 0 ){
		return;
	}
	astLink = ccNewLinkage( astSym, usDeclKind, usLinkKind );
	stSymbolInfoAccess.linkage.set( astSym, astLink );
}

